class h_teacher {

	constructor() {
	
	}

	checkTchId(tchId) {
		return this._checkTchId(tchId)
	}

	/**
	 *
	 * [public] 根据微信用户ID获取教师数据
	 *
	 * @param [string] userId  已绑定教师身份的微信用户ID
	 *
	 * @return [object] tchData 教师数据
	 *
	 */

	async getTchDataByUserId(userId, ...fields) {
		if(!userId)
			return this.reject('-2020', 'user id invalid')
		const tchData = await this._getTchDataByUserId(userId, ...fields)
		if(!tchData)
			return this.reject('-2012', 'teacher not found')
		return this.resolve(tchData)
	}

	async checkTchBind(tchId) {
		return await this._checkTchBind(tchId)
	}

	encryptTchPwd(tchId, tchPwd) {
		return this._encryptTchPwd(tchId, tchPwd)
	}

	/**
	 *
	 * [public] 绑定教师用户
	 *
	 * @param [string] stuId 教师工号
	 * @param [string] tchPwd 教师密码
	 * @param [object] user 用户对象
	 *
	 * @return [promise] tchData 教师数据
	 *
	 */

	async bindTchUser(tchId, tchPwd, tchInfo, user) {
		const {type, userId, session} = user
		if(!this.checkTchId(tchId))
			return this.reject('-2011', 'teacher id invalid')
		const tchData = await this._getTchDataByTchId(tchId, 'tchId', 'tchName', 'tchSex', 'tchPhoto', 'tchFaculty', 'tchStaffRoom', 'tchPhone', 'tchBirth', 'tchNation', 'tchPolicital', 'tchEmail', 'tchUniversity', 'tchMajor', 'tchEdu', 'tchDegree', 'tchTitle', 'tchJob', 'tchSubject', 'tchCertNum', 'tchLectureNum', 'tchHumanId', 'tchIsExperimenter', 'tchEvaluation', 'tchSummary', 'tchBindDate')
		await this.mysql.cxxy.trans()
		const facultyData = await this.hd.department.addFaculty(tchInfo.tchFaculty)
		const staffRoomData = await this.hd.department.addStaffRoom(tchInfo.tchStaffRoom)
		tchInfo.tchFaculty = facultyData.facultyId
		tchInfo.tchStaffRoom = staffRoomData.staffRoomId
		await this.hd.syllabus.addTchCourseData(tchId, tchInfo.courseClasses, tchInfo.tchSyllabus, tchInfo.courseTime)
		let result = {}
		if(!tchData) {
			tchInfo.tchPwd = tchPwd
			await this._addTchData(userId, tchInfo)
			result = {
				tchId,
				tchName: tchInfo.tchName,
				tchSex: tchInfo.tchSex
			}
		}
		else if(tchData.userId != '') {
			await this.common.updateSessionType(user.session, 'normal')
			return this.reject('-2003', 'teacher bind id only one time')
		}
		else {
			const newTchData = await this._updateTchData(tchId, userId, tchInfo, tchData)
			result = {
				tchId: newTchData.tchId,
				tchName: newTchData.tchName,
				tchSex: newTchData.tchSex
			}
		}
		await this.mysql.cxxy.update({
			table: 'user',
			field: `userType='teacher'`,
			where: 'userId=$userId',
			data: {
				userId
			}
		})
		await this.mysql.cxxy.cmt()
		if(type != 'teacher')
			await this.common.updateSessionType(session, 'teacher')
		return this.resolve(result)
	}

	//解绑教师用户
	async untieTchUser(user) {
		const {userId, session} = user
		const result = await this._getTchDataByUserId(userId, 'tchId', 'tchPwd', 'tchHashPwd', 'tchZfAuthId', 'tchName', 'tchSex', 'tchPhoto', 'tchFaculty', 'tchSCardId', 'tchNation', 'tchBirth', 'tchPolicital', 'tchPhone', 'tchEmail', 'tchUniversity', 'tchMajor', 'tchEdu', 'tchDegree', 'tchTitle', 'tchJob', 'tchSubject', 'tchCertNum', 'tchLectureNum', 'tchHumanId', 'tchIsExperimenter', 'tchEvaluation', 'tchSummary', 'tchSuspend', 'tchBindDate')
		if(!result)
			return this.reject('-2070', 'user not bind teacher')
		const {tchId} = result
		await this.mysql.cxxy.trans()
		//更新教师绑定身份
		await this.mysql.cxxy.update({
			table: 'teacher',
			field: [
				`userId=''`,
				'tchUntie=1',
				'tchUntieDate=$tchUntieDate'
			],
			where: 'tchId=$tchId',
			data: {
				tchUntieDate: this.common.timestamp(),
				tchId
			}
		})
		//更新教职工绑定身份
		await this.mysql.cxxy.update({
			table: 'user',
			field: `userType=''`,
			where: `userType='teacher' and userId=$userId`,
			data: {
				userId
			}
		})
		await this.mysql.cxxy.cmt()
		//删除用户数据缓存
		await this._clearTchDataCacheByStuId(tchId)
		await this._clearTchDataCacheByUserId(userId)
		//删除任教班级列表缓存
		await this._clearTchClassesCache(tchId)
		//删除一卡通缓存
		await this.hd.card.clearTchCardCache(userId)
		//删除用户借阅记录缓存
		await this.hd.library.clearUserLibraryLoanCache(userId)
		//更新用户状态为normal
		await this.common.updateSessionType(session, 'normal')
	}

	async getTchClassesCache(tchId) {
		return await this.redis.cache.get(`tchClasses@${tchId}`, true)
	}

	async getTchTodayCourseCache(tchId) {
		return await this.redis.cache.get(`tchTodayCourse@${tchId}`, true)
	}

	//获取教师任教班级列表
	async getTchClasses(tchId) {
		return await this._getTchClasses(tchId)
	}

	//获取教师今天课程列表
	async getTchTodayCourse(tchId) {
		const {courseYear, courseTerm, courseStartDate} = await this.hd.sys.getCommonData('courseYear', 'courseTerm', 'courseStartDate')
		const result = await this.mysql.cxxy.select({
			table: [
				'course c',
				'course_relation r',
				'major m',
				'class l',
				'classroom o'
			],
			field: [
				'c.courseId',
				'courseName',
				'coursePitch',
				'c.majorId',
				'm.majorName',
				'c.classId',
				'l.classGrade',
				'l.className',
				'c.roomId',
				'o.roomName',
				'startWeek',
				'endWeek',
				'doubleWeek'
			],
			where: 'tchId=$tchId && courseDay=$courseDay && c.courseYear=$courseYear && c.courseTerm=$courseTerm && startWeek<=$nowWeek && endWeek>=$nowWeek && r.courseId=c.courseId && l.classId=c.classId && m.majorId=c.majorId && o.roomId=c.roomId',
			data: {
				tchId,
				courseYear,
				courseTerm,
				courseDay: 2,//(new Date()).getDay(),
				nowWeek: 8//parseInt((this.common.timestamp() - courseStartDate) / 60 / 60 / 24 / 7)
			}
		})
		return result
	}

	//检查此教师是否任教此班级
	async checkTchClass(tchId, classId) {
		const result = await this._getTchClasses(tchId)
		if(result.length == 0)
			return this.reject('-2072', 'teacher not have this class auth')
	}

	//添加点名单
	async addCallNameTable(tchId, classId, callNameResult) {
		const {ignore, sign, late, absent, leave, earlyLeave, suspend} = callNameResult
		const callId = await this.common.createRandomStr(32)
		const result = await this.mysql.cxxy.insert({
			table: 'call_name',
			field: [
				'callId=$callId',
				'callTchId=$callTchId',
				'callClass=$callClass',
				'callData=$callData',
				'ignoreCount=$ignoreCount',
				'signCount=$signCount',
				'lateCount=$lateCount',
				'absentCount=$absentCount',
				'leaveCount=$leaveCount',
				'earlyLeaveCount=$earlyLeaveCount',
				'suspendCount=$suspendCount',
				'callDate=$callDate'
			],
			data: {
				callId,
				callTchId: tchId,
				callClass: classId,
				callData: JSON.stringify(callNameResult),
				ignoreCount: ignore.length,
				signCount: sign.length,
				lateCount: late.length,
				absentCount: absent.length,
				leaveCount: leave.length,
				earlyLeaveCount: earlyLeave.length,
				suspendCount: suspend.length,
				callDate: this.common.timestamp()
			}
		})
		if(result == 0)
			return this.reject('-2087', 'create call name table failed')
		return callId
	}

	async clearTchClassesCache(tchId) {
		await this._clearTchClassesCache(tchId)
	}

	async clearTchDataCacheByUserId(userId) {
		await this._clearTchDataCacheByUserId(userId)
	}

	async _clearTchClassesCache(tchId) {
		await this.redis.cache.delete(`tchClasses@${tchId}`)
	}

	async _clearTchDataCacheByStuId(tchId) {
		await this.redis.user.delete(`teacher@${tchId}`)
	}

	async _clearTchDataCacheByUserId(userId) {
		await this.redis.user.delete(`teacher@${userId}`)
	}

	async _checkTchBind(tchId) {
		if(!this._checkTchId(tchId))
			return this.reject('-2010', 'teacher id invalid')
		const tchData = await this._getTchDataByTchId(tchId, 'userId')
		return tchData && tchData.userId != '' && stuData.tchUntie == 0
	}

	async _addTchData(userId, tchData) {
		const {tchId, tchPwd, tchZfAuthId, tchName, tchSex, tchPhoto, tchFaculty, tchStaffRoom, tchNation, tchBirth, tchPolicital, tchPhone, tchEmail, tchUniversity, tchMajor, tchEdu, tchDegree, tchTitle, tchJob, tchSubject, tchCertNum, tchLectureNum, tchHumanId, tchIsExperimenter, tchEvaluation, tchSummary} = tchData
		const tchHashPwd = this._encryptTchPwd(tchId, tchPwd)
		const result = await this.mysql.cxxy.insert({
			table: 'teacher',
			field: [
				'userId',
				'tchId',
				'tchPwd',
				'tchHashPwd',
				'tchZfAuthId',
				'tchName',
				'tchSex',
				'tchPhoto',
				'tchFaculty',
				'tchStaffRoom',
				'tchNation',
				'tchBirth',
				'tchPolicital',
				'tchPhone',
				'tchEmail',
				'tchUniversity',
				'tchMajor',
				'tchEdu',
				'tchDegree',
				'tchTitle',
				'tchJob',
				'tchSubject',
				'tchCertNum',
				'tchLectureNum',
				'tchHumanId',
				'tchIsExperimenter',
				'tchEvaluation',
				'tchSummary',
				'tchBindDate'
			],
			data: {
				userId,
				tchId,
				tchPwd,
				tchHashPwd,
				tchZfAuthId,
				tchName,
				tchSex,
				tchPhoto,
				tchFaculty,
				tchStaffRoom,
				tchNation,
				tchBirth,
				tchPolicital,
				tchPhone,
				tchEmail,
				tchUniversity,
				tchMajor,
				tchEdu,
				tchDegree,
				tchTitle,
				tchJob,
				tchSubject,
				tchCertNum,
				tchLectureNum,
				tchHumanId,
				tchIsExperimenter,
				tchEvaluation,
				tchSummary,
				tchBindDate: this.common.timestamp()
			}
		})
		if(result == 0)
			return this.reject('-2019', 'add new teacher data failed')
	}

	async _updateTchData(tchId, userId, tchData, oldTchData) {
		let updateKeys = []
		tchData.userId = userId
		for(let key in oldTchData) {
			if(tchData[key] && tchData[key] != oldTchData[key]) {
				updateKeys.push(`${key}=$${key}`)
				oldTchData[key] = tchData[key]
			}
		}
		if(Object.keys(oldTchData).length > 0) {
			console.log(`teacher ${tchData.stuName} data is change`)
			oldTchData.tchId = tchId
			await this.mysql.cxxy.update({
				table: 'teacher',
				field: updateKeys,
				where: 'tchId=$tchId',
				data: oldTchData
			})
		}
		else {
			console.log(`teacher ${oldTchData.stuName} data is up-to-date`)
		}
		return oldTchData
	}

	async _getTchDataByTchId(tchId, ...fields) {
		let tchData = await this.redis.user.get(`teacher@${tchId}`, true)
		if(!tchData) {
			tchData = await this.mysql.cxxy.select({
				table: 'teacher',
				field: fields || 'userId',
				where: 'tchId=$tchId',
				data: {
					tchId
				}
			})
			tchData = tchData[0]
		}
		else {
			const keys = Object.keys(tchData)
			const fieldsArr = !fields ? [] : fields
			const noFields = fieldsArr.filter((key) => {
				return keys.indexOf(this.common.trim(key)) == -1
			})
			if(noFields.length != 0) {
				const temp = await this.mysql.cxxy.select({
					table: 'teacher',
					field: noFields,
					where: 'tchId=$tchId',
					data: {
						tchId
					}
				})
				if(temp[0])
					Object.assign(tchData, temp[0])
			}
		}
		if(tchData)
			await this.redis.user.set(`teacher@${tchId}`, tchData, this.config.frame.sessionExpires.student)
		return tchData ? tchData : null
	}

	/**
	 *
	 * [private] 根据微信用户ID获取教师数据
	 *
	 * @param [string] userId  已绑定教师身份的微信用户ID
	 *
	 * @return [object] tchData 教师数据
	 *
	 */

	async _getTchDataByUserId(userId, ...fields) {
		let tchData = await this.redis.user.get(`teacher@${userId}`, true)
		if(!tchData) {
			tchData = await this.mysql.cxxy.select({
				table: 'teacher',
				field: fields || 'userId',
				where: 'userId=$userId',
				data: {
					userId
				}
			})
			tchData = tchData[0]
		}
		else {
			const keys = Object.keys(tchData)
			const fieldsArr = !fields ? [] : fields
			const noFields = fieldsArr.filter((key) => {
				return keys.indexOf(this.common.trim(key)) == -1
			})
			if(noFields.length != 0) {
				const temp = await this.mysql.cxxy.select({
					table: 'teacher',
					field: noFields,
					where: 'userId=$userId',
					data: {
						userId
					}
				})
				if(temp[0])
					Object.assign(tchData, temp[0])
			}
		}
		if(tchData)
			await this.redis.user.set(`teacher@${userId}`, tchData, this.config.frame.sessionExpires.teacher)
		return tchData
	}

	async _getTchClasses(tchId) {
		const classes = await this.mysql.cxxy.select({
			distinct: true,
			table: [
				'course_relation r',
				'course o',
				'class c'
			],
			field: [
				'c.classId',
				'c.classGrade',
				'c.className'
			],
			where: 'o.courseId=r.courseId && o.classId=c.classId && r.tchId=$tchId',
			sort: {
				field: ['c.classGrade', 'c.className'],
				order: 'asc'
			},
			data: {
				tchId
			}
		})
		await this.redis.cache.set(`tchClasses@${tchId}`, classes, this.config.frame.sessionExpires.tchClasses)
		return classes
	}

	_checkTchId(tchId) {
		return /^\w{4,}/.test(tchId)
	}

	/**
	 *
	 * [private] 加密教师密码
	 *
	 * @param tchId 教师工号
	 * @param tchPwd 教师密码
	 *
	 * @return [string] 加密后的密码
	 *
	 */

	_encryptTchPwd(tchId = '', tchPwd) {
		return this.crypto.sha256(this.crypto.sha256(tchId + tchPwd) + this.config.frame.pwdSalt)
	}

}

module.exports = h_teacher